/*
 * @Author       : LuHeQiu
 * @Date         : 2023-04-22 01:51:50
 * @LastEditTime : 2023-04-29 14:50:17
 * @LastEditors  : LuHeQiu
 * @Description  :
 * @FilePath     : /UnionLink-Ctrl/Hardware/rf.c
 * @HomePage     : https://www.luheqiu.com
 */
#include "rf.h"
#include "rf_reg.h"
#include "spi.h"

#define RF_SET_CE_LOW() HAL_GPIO_WritePin(RF_CE_GPIO_Port, RF_CE_Pin, GPIO_PIN_RESET)
#define RF_SET_CE_HIGH() HAL_GPIO_WritePin(RF_CE_GPIO_Port, RF_CE_Pin, GPIO_PIN_SET)
#define RF_SET_CS_LOW() HAL_GPIO_WritePin(RF_CSN_GPIO_Port, RF_CSN_Pin, GPIO_PIN_RESET)
#define RF_SET_CS_HIGH() HAL_GPIO_WritePin(RF_CSN_GPIO_Port, RF_CSN_Pin, GPIO_PIN_SET)

#define RF_Write_Byte(pTxData) HAL_SPI_Transmit(&hspi2, (uint8_t[]){pTxData}, 1, 500)
#define RF_Write_Bytes(pTxData, size) HAL_SPI_Transmit(&hspi2, (pTxData), (size), 500)
#define RF_Read_Bytes(pRxData, size) HAL_SPI_Receive(&hspi2, (pRxData), (size), 500)
#define RF_Write_Read_Bytes(pTxData, pRxData, size) HAL_SPI_TransmitReceive(&hspi2, (pTxData), (pRxData), (size), 500)

/**
 * @brief  RF_Module 检测
 * @retval RF工作正常标志
 */
uint8_t RF_Check(void) {
    uint8_t i;
    uint8_t buf[5] = {0X0F, 0X0F, 0X0F, 0X0F, 0X0F};
    uint8_t read_buf[5] = {0};

    RF_Write_Buf(TX_ADDR, buf, 5);     /* 写入5个字节的地址 */
    RF_Read_Buf(TX_ADDR, read_buf, 5); /* 读出写入的地址    */
    for (i = 0; i < 5; i++) {
        if (buf[i] != read_buf[i]) {
            break;
        }
    }

    return (i == 5);
}

/**
 * @brief  RF_Module 初始化
 * @param  local_addr 本机地址
 * @retval none
 */
void RF_Init(uint8_t* local_addr) {
    uint8_t addr[5] = RF_RADIO_CHANNEL;

    // RF_SET_CE_HIGH();
    RF_Clear_IRQ_Flag(IRQ_ALL);
#if DYNAMIC_PACKET == 1

    RF_Write_Reg(DYNPD, (1 << 0) | (1 << 1));  //* 使能通道0、1动态数据长度 */
    RF_Write_Reg(FEATRUE, 0x05);
    RF_Read_Reg(DYNPD);
    RF_Read_Reg(FEATRUE);

#elif DYNAMIC_PACKET == 0

    L01_WriteSingleReg(L01REG_RX_PW_P0, FIXED_PACKET_LEN);  // 固定数据长度

#endif

    RF_Write_Reg(CONFIG, /*( 1<<MASK_RX_DR ) |*/                /* 接收中断(不启用)              */
                             (1 << EN_CRC) |                    /* 使能CRC 1个字节               */
                             (1 << PWR_UP));                    /* 开启设备                      */
    RF_Write_Reg(EN_AA, (1 << ENAA_P0) | (1 << ENAA_P1));       /* 通道0、1自动应答                 */
    RF_Write_Reg(EN_RXADDR, (1 << ERX_P0) | (1 << ERX_P1));     /* 通道0、1接收                     */
    RF_Write_Reg(SETUP_AW, AW_4BYTES);                          /* 地址宽度 4个字节              */
    RF_Write_Reg(SETUP_RETR, ARD_1000US | (REPEAT_CNT & 0x0F)); /* 重复等待时间 4000us 重复15次  */
    RF_Write_Reg(RF_CH, 0x05);                                  /* 初始化通道 2405MHZ            */
    RF_Write_Reg(RF_SETUP, 0x26 | 0x00 << CONT_WAVE);           /* 数据速率250kbps、发射功率4dbm */

    RF_SetTxAddr(addr, RF_ADDR_WIDTH);          /* 设置TX地址     */
    RF_SetRxAddr(0, addr, RF_ADDR_WIDTH);       /* 设置RX广播地址 */
    RF_SetRxAddr(1, local_addr, RF_ADDR_WIDTH); /* 设置RX本机地址 */
}

/**
 * @brief  设置模式
 * @param  Mode 模式发送模式或接收模式，可选值为 RF_MODE_TX RF_MODE_RX。
 * @retval 无
 */
void RF_SetMode(RF_ModeType Mode) {
    uint8_t controlreg = 0;
    controlreg = RF_Read_Reg(CONFIG);

    RF_SET_CE_LOW();
    if (Mode == RF_MODE_TX) {
        controlreg &= ~(1 << PRIM_RX);
        RF_SET_CE_LOW();
    } else if (Mode == RF_MODE_RX) {
        uint8_t l_MsTimes;
        while ((RF_Read_Reg(STATUS) & RF_TX_OK) == 0) {
            HAL_Delay(1);
            if ((l_MsTimes++) == 10)break; /* 100ms还没有发送成功 */            
        }
        controlreg |= (1 << PRIM_RX);
        RF_SET_CE_HIGH();
    }

    RF_Write_Reg(CONFIG, controlreg);
}

void RF_SetModeForce(RF_ModeType Mode) {
    uint8_t controlreg = 0;
    controlreg = RF_Read_Reg(CONFIG);

    RF_SET_CE_LOW();
    if (Mode == RF_MODE_TX) {
        controlreg &= ~(1 << PRIM_RX);
        RF_SET_CE_LOW();
    } else if (Mode == RF_MODE_RX) {
        controlreg |= (1 << PRIM_RX);
        RF_SET_CE_HIGH();
    }

    RF_Write_Reg(CONFIG, controlreg);
}

/**
 * @brief  RF 发送数据包
 * @param  txbuf 数据存放地址
 * @param  Length 待发送的数据长度
 * @retval 发送状态 TX_OK:发送成功
 */
uint8_t RF_TxPacket(uint8_t* txbuf, uint8_t Length) {

    uint8_t l_Status = 0;
    uint16_t l_MsTimes = 0;

    RF_Write_Reg(FLUSH_TX, 0xff);  /* 清除TX FIFO寄存器 */ 

    RF_SetMode(RF_MODE_TX);

    RF_SET_CE_LOW();                               /* CE=0 确保处于待机模式Standby */
    RF_Write_Buf(WR_TX_PLOAD_NACK, txbuf, Length); /* 写数据到TX BUF TX_PLOAD_WIDTH */
    RF_SET_CE_HIGH();                              /* 启动发送 */

    while ((RF_Read_Reg(STATUS) & RF_TX_OK) == 0) {
        HAL_Delay(1);
        if ((l_MsTimes++) == 500) /* 500ms还没有发送成功 */
        {
            // RF_Init();
            // RF_SetMode(RF_MODE_RX);
            break;
        }
    }
    l_Status = RF_Read_Reg(STATUS); /* 读状态寄存器              */
    RF_Write_Reg(STATUS, l_Status); /* 清除TX_DS或MAX_RT中断标志 */

    RF_SET_CE_LOW();
    RF_SetMode(RF_MODE_RX);

    if (l_Status & RF_TX_MAX)  // 达到最大重发次数
    {
        RF_Write_Reg(FLUSH_TX, 0xff);  // 清除TX FIFO寄存器
        return RF_TX_MAX;
    }
    if (l_Status & RF_TX_OK)  // 发送完成
    {
        return RF_TX_OK;
    }

    return 0xFF;  // 其他原因发送失败
}

/**
 * @brief  RF 接收数据包
 * @param  rxbuf 数据存放地址，请确保空间足够 32bytes 以防溢出。
 * @param  channel 收到数据的通道编号
 * @retval 接收缓冲区数据比特数，0表示无数据
 */
uint8_t RF_RxPacket(uint8_t* rxbuf, uint8_t* channel) {
    uint8_t l_Status = 0, l_RxLength = 0;

    l_Status = RF_Read_Reg(STATUS);  // 读状态寄存器

    if (l_Status & RF_RX_OK)  // 接收到数据
    {
        *channel = (l_Status >> 1) & 0x07;
        RF_Write_Reg(STATUS, l_Status);  // 清中断标志
        l_RxLength = RF_Read_Reg(R_RX_PL_WID);        // 读取接收到的数据个数
        RF_Read_Buf(RD_RX_PLOAD, rxbuf, l_RxLength);  // 接收到数据
        
        RF_Write_Reg(FLUSH_RX, 0xff);                 // 清除RX FIFO
        return l_RxLength;
    }

    return 0;  // 没有收到数据
}


void RF_TxDataDirect(uint8_t* txbuf, uint8_t Length){
    if(Length>32||Length==0){
        return;
    }
    RF_Clear_IRQ_Flag(TX_DS | MAX_RT); /* 清除TX_DS或MAX_RT中断标志 */
    RF_SET_CE_LOW(); 
    RF_Write_Buf(WR_TX_PLOAD_NACK, txbuf, Length); /* 写数据到TX BUF TX_PLOAD_WIDTH */
    RF_SET_CE_HIGH();
}


/**
 * @brief  获取RSSI值，可用于载波检测
 * @retval 占用为1，空闲为0
 */
uint8_t RF_GetRSSI(void){
    uint8_t cd;
    RF_SET_CE_HIGH();
    RF_SET_CE_LOW();
    cd = RF_Read_Reg(CD);
    RF_SET_CE_HIGH();
    return cd;
}

/**
 * @brief  设置发送地址
 * @param  pAddr 地址存放地址
 * @param  len 长度
 * @retval none
 */
void RF_SetTxAddr(uint8_t* pAddr, uint8_t len) {
    len = (len > RF_ADDR_WIDTH) ? RF_ADDR_WIDTH : len;          // 地址不能大于5个字节
    RF_Write_Buf(TX_ADDR, pAddr, len);  // 写地址
}

/**
 * @brief  设置接收通道地址
 * @param  PipeNum 通道
 * @param  pAddr 地址
 * @param  Len 长度
 * @note   通道不大于5 地址长度不大于5个字节
 * @retval none
 */
void RF_SetRxAddr(uint8_t PipeNum, uint8_t* pAddr, uint8_t Len) {
    Len = (Len > RF_ADDR_WIDTH) ? RF_ADDR_WIDTH : Len;
    PipeNum = (PipeNum > 5) ? 5 : PipeNum;                // 通道不大于5 地址长度不大于5个字节

    RF_Write_Buf(RX_ADDR_P0 + PipeNum, pAddr, Len);  // 写入地址
}

/**
 * @brief  设置频率
 * @param  FreqPoint 频率设置参数
 * @note   值不大于125
 * @retval 无
 */
void RF_SerHoppingPoint(uint8_t FreqPoint) {
    FreqPoint = (FreqPoint > 125) ? 125 : FreqPoint;
    RF_Write_Reg(RF_CH, FreqPoint & 0x7F);
}

/**
 * @brief  设置通信速度
 * @param  Speed 速度
 * @note   无
 * @retval 无
 */
void RF_SetSpeed(RF_SpeedType Speed) {
    uint8_t btmp = 0;

    btmp = RF_Read_Reg(RF_SETUP);
    btmp &= ~((1 << 5) | (1 << 3));

    switch (Speed) {
        case RF_SPEED_250K:
            btmp |= (1 << 5);
            break;
        case RF_SPEED_1M:
            btmp &= ~((1 << 5) | (1 << 3));
            break;
        case RF_SPEED_2M:
            btmp |= (1 << 3);
            break;
        default:
            break;
    }

    RF_Write_Reg(RF_SETUP, btmp);
}

 /**
  * @brief :设置功率
  * @param :
  *			@Speed:速度
  * @note  :无
  * @retval:无
  */
void RF_SetPower( RF_PowerType Power )
{
    uint8_t btmp;

    btmp = RF_Read_Reg(RF_SETUP) & ~0x07;
    btmp |= ((uint8_t)Power & 0x07);
    RF_Write_Reg(RF_SETUP, btmp);
}


/**
 * @brief  RF读寄存器
 * @param  Addr 寄存器地址
 * @note   地址在设备中有效
 * @retval 读取的数据
 */
uint8_t RF_Read_Reg(uint8_t RegAddr) {
    uint8_t btmp;
    RF_SET_CS_LOW();                                         // 片选
    RF_Write_Bytes((uint8_t[]){NRF_READ_REG | RegAddr}, 1);  // 读命令 地址
    RF_Write_Read_Bytes((uint8_t[]){0xFF}, &btmp, 1);        // 读数据
    RF_SET_CS_HIGH();                                        // 取消片选
    return btmp;
}

/**
 * @brief  RF读指定长度的数据
 * @param  reg 地址
 * @param  pBuf 数据存放地址
 * @param  len 数据长度
 * @note   数据长度不超过255，地址在设备中有效
 * @retval 读取状态
 */
void RF_Read_Buf(uint8_t RegAddr, uint8_t* pBuf, uint8_t len) {
    RF_SET_CS_LOW();                                                                 // 片选
    RF_Write_Read_Bytes((uint8_t[]){NRF_READ_REG | RegAddr}, (uint8_t[]){0xFF}, 1);  // 读命令 地址
    for (int i = 0; i < len; i++) {
        RF_Write_Read_Bytes((uint8_t[]){0xFF}, pBuf + i, 1);  // 读数据
    }
    RF_SET_CS_HIGH();  // 取消片选
}

/**
 * @brief  RF写寄存器
 * @param  RegAddr
 * @param  Value
 * @note   地址在设备中有效
 * @retval none
 */
void RF_Write_Reg(uint8_t RegAddr, uint8_t Value) {
    RF_SET_CS_LOW();  // 片选
    RF_Write_Bytes(((uint8_t[]){NRF_WRITE_REG | RegAddr, Value}), 2);
    RF_SET_CS_HIGH();  // 取消片选
}

/**
 * @brief  RF 写指定长度的数据
 * @param  reg 地址
 * @param  pBuf 写入的数据地址
 * @param  len 数据长度
 * @note   数据长度不超过255，地址在设备中有效
 * @retval none
 */
void RF_Write_Buf(uint8_t RegAddr, uint8_t* pBuf, uint8_t len) {
    RF_SET_CS_LOW();                                                                  // 片选
    RF_Write_Read_Bytes((uint8_t[]){NRF_WRITE_REG | RegAddr}, (uint8_t[]){0xFF}, 1);  // 写命令 地址
    for (int i = 0; i < len; i++) {
        RF_Write_Read_Bytes(pBuf + i, (uint8_t[]){0xFF}, 1);  // 读数据
    }
    // RF_Write_Bytes(pBuf, len);                               // 写数据
    RF_SET_CS_HIGH();  // 取消片选
}

/**
 * @brief  RF_Module 清除中断
 * @param  IRQ_Source 中断源
 * @retval 清除后状态寄存器的值
 */
uint8_t RF_Clear_IRQ_Flag(uint8_t IRQ_Source) {
    uint8_t btmp = 0;

    IRQ_Source &= (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT);  // 中断标志处理
    btmp = RF_Read_Status_Register();                           // 读状态寄存器

    RF_SET_CS_LOW();                                                                 // 片选
    RF_Write_Read_Bytes((uint8_t[]){NRF_WRITE_REG | STATUS}, (uint8_t[]){0xff}, 1);  // 写状态寄存器命令
    RF_Write_Read_Bytes((uint8_t[]){IRQ_Source | btmp}, (uint8_t[]){0xff}, 1);       // 清相应中断标志
    RF_SET_CS_HIGH();                                                                // 取消片选

    return (RF_Read_Status_Register());  // 返回状态寄存器状态
}

/**
 * @brief  RF_Module 读状态寄存器
 * @retval 状态
 */
uint8_t RF_Read_Status_Register(void) {
    uint8_t status;
    RF_SET_CS_LOW();                                                      // 片选
    RF_Write_Read_Bytes((uint8_t[]){NRF_READ_REG | STATUS}, &status, 1);  // 读状态寄存器
    RF_SET_CS_HIGH();                                                     // 取消片选
    return status;
}
